feat: Support jsi::NativeState in Shareables#5785
feat: Support jsi::NativeState in Shareables#5785tomekzaw merged 5 commits intosoftware-mansion:mainfrom
jsi::NativeState in Shareables#5785Conversation
|
I think If so, I could also add guards to make sure this is not part of builds on RN 0.70 or lower. lmk |
|
done |
|
I see you did it exactly the same as in my PR, nice. The other thing we would probably need is something similar to https://github.com/software-mansion/react-native-reanimated/pull/5734/files#diff-de926588e6942029aeecf8c65e8d8292808b725b95b6bcf22b421425fd10664eR150. Did you check it on 0.74 maybe? |
|
Ah lol - that was coincidentally exactly the same approach, didn't even see your PR 😂 Okay well I mean my PR unblocks me right now, if you intend to merge your PR soon then I guess we can close my PR? Otherwise we can use my PR as an intermediate solution where all I only tried this in RN 0.73, not 0.74 - I don't think we need that check as it is always a |
|
Added some more code to properly handle passing objects with Here's how this PR can be tested in Reanimated Example app: RNRuntimeDecorator.hclass MyNativeState : public jsi::NativeState {
public:
explicit MyNativeState(int number) : number_(number) {}
int number_;
};RNRuntimeDecorator.cpp auto setNativeState = jsi::Function::createFromHostFunction(
rnRuntime,
jsi::PropNameID::forAscii(rnRuntime, "setNativeState"),
2,
[](jsi::Runtime &rt,
const jsi::Value &thisValue,
const jsi::Value *arguments,
size_t count) -> jsi::Value {
auto state = std::make_shared<MyNativeState>(arguments[1].asNumber());
arguments[0].asObject(rt).setNativeState(rt, state);
return jsi::Value::undefined();
});
rnRuntime.global().setProperty(
rnRuntime, "setNativeState", std::move(setNativeState));
auto getNativeState = jsi::Function::createFromHostFunction(
rnRuntime,
jsi::PropNameID::forAscii(rnRuntime, "getNativeState"),
1,
[](jsi::Runtime &rt,
const jsi::Value &thisValue,
const jsi::Value *arguments,
size_t count) -> jsi::Value {
const auto &obj = arguments[0].asObject(rt);
if (!obj.hasNativeState(rt)) {
return jsi::Value::undefined();
}
return jsi::Value(obj.getNativeState<MyNativeState>(rt)->number_);
});
rnRuntime.global().setProperty(
rnRuntime, "getNativeState", std::move(getNativeState));ShareablesExample.tsxfunction NativeStateJSToUIDemo() {
const handlePress = () => {
const obj = {};
// @ts-expect-error
const { setNativeState, getNativeState } = global;
setNativeState(obj, Math.random() * 1000);
console.log(_WORKLET ? 'UI' : 'JS', getNativeState(obj));
runOnUI(() => {
console.log(_WORKLET ? 'UI' : 'JS', getNativeState(obj));
})();
};
return <Button title="NativeState JS->UI" onPress={handlePress} />;
}
function NativeStateUIToJSDemo() {
const handlePress = () => {
// @ts-expect-error
const { setNativeState, getNativeState } = global;
function jsCallback(obj: object) {
console.log(_WORKLET ? 'UI' : 'JS', getNativeState(obj));
}
runOnUI(() => {
const obj = {};
setNativeState(obj, Math.random() * 1000);
console.log(_WORKLET ? 'UI' : 'JS', getNativeState(obj));
runOnJS(jsCallback)(obj);
})();
};
return <Button title="NativeState UI->JS" onPress={handlePress} />;
} |
|
Awesome! Thanks guys! |
Summary
Allows Shared Objects to also retain their
NativeStatewhen copied between runtimes.Assuming this object:
..gets sent to JS, if it will be used in a Worklet runtime it will only contain the
"name"property, and it's native state field will be null.With this PR,
jsi::NativeStatealso gets copied over to the JS object if it is shared between runtimes, which is safe to do because it is ashared_ptralready.Test plan
Try to use an object with Native State (e.g. VisionCamera v4 tests) in a Worklet runtime.